
/* 解析流程备忘
 * 1. 获取协议列表，得到协议名(short_name)
 * 2. 由协议名得到协议句柄
 * 3. 根据协议句柄判断协议是否使能
 * 4. 调用使能协议的解析方法
 * 5. 解析出错返回 -1，协议完全性检查失败返回 0，解析完返回数据长度
 * 6. ？需要添加完全性检查方法(integrity)吗？
 * 7. 根据(integrity)返回真值判断完全性还是交给(dissector)判断？
 */

struct tvbuff {
    /* Doubly linked list pointers */
    tvbuff_t               *next;

    /* Record-keeping */
    const struct tvb_ops   *ops;
    bool                    initialized;
    unsigned                flags;
    struct tvbuff           *ds_tvb;  /**< data source top-level tvbuff */

    /** Pointer to the data for this tvbuff.
     * It might be null, which either means that 1) it's a
     * zero-length tvbuff or 2) the tvbuff was lazily
     * constructed, so that we don't allocate a buffer of
     * backing data and fill it in unless we need that
     * data, e.g. when tvb_get_ptr() is called.
     */
    const uint8_t           *real_data;

    /** Amount of data that's available from the capture
     * file.  This is the length of virtual buffer (and/or
     * real_data).  It may be less than the reported
     * length if this is from a packet that was cut short
     * by the capture process.
     *
     * This must never be > reported_length or contained_length. */
    unsigned            length;
    unsigned            reported_length;
    unsigned            contained_length;

    /* Offset from beginning of first "real" tvbuff. */
    int            raw_offset;
};
typedef struct tvbuff tvbuff_t;


typedef struct _packet_info {
    const char   *proto_name;        /**< name of protocol currently being dissected */
    uint32_t      presence_flags;           /**< Presence flags for some items */
    uint32_t      num;                      /**< Frame number */
    //  frame_data *fd;
    GSList       *data_src;                 /**< Frame data sources */

    uint32_t      match_uint;               /**< matched uint for calling subdissector from table */
    const char   *match_string;         /**< matched string for calling subdissector from table */


    GHashTable   *private_table;    /**< a hash table passed from one dissector to another */

//  wmem_list_t *layers;          /**< layers of each protocol */
//  wmem_map_t *proto_layers;     /** map of proto_id to curr_proto_layer_num. */
    uint8_t curr_layer_num;        /**< The current "depth" or layer number in the current frame */
    uint8_t curr_proto_layer_num;  /**< The current "depth" or layer number for this dissector in the current frame */

    int dissection_depth;         /**< The current "depth" or layer number in the current frame */

    uint32_t stream_id;            /**< Conversation Stream ID of the highest protocol */
} packet_info;



typedef struct _header_field_info hf_info;

/** information describing a header field */
struct _header_field_info {
    /* ---------- set by dissector --------- */
    const char        *name;              /**< [FIELDNAME] full name of this field */
    const char        *abbrev;            /**< [FIELDFILTERNAME] filter name of this field */
    enum ftenum        type;              /**< [FIELDTYPE] field type, one of FT_ (from ftypes.h) */
    int                display;           /**< [FIELDDISPLAY] one of BASE_, or field bit-width if FT_BOOLEAN and non-zero bitmask */
    const void        *strings;           /**< [FIELDCONVERT] value_string, val64_string, range_string or true_false_string,
                                               typically converted by VALS(), RVALS() or TFS().
                                               If this is an FT_PROTOCOL or BASE_PROTOCOL_INFO then it points to the
                                               associated protocol_t structure */
    uint64_t           bitmask;           /**< [BITMASK] bitmask of interesting bits */
    const char        *blurb;             /**< [FIELDDESCR] Brief description of field */

    /* ------- set by proto routines (prefilled by HFILL macro, see below) ------ */
    int                id;                /**< Field ID */
    int                parent;            /**< parent protocol tree */
    hf_ref_type        ref_type;          /**< is this field referenced by a filter */
    int                same_name_prev_id; /**< ID of previous hfinfo with same abbrev */
    hf_info           *same_name_next;    /**< Link to next hfinfo with same abbrev */
};

/** string representation, if one of the proto_tree_add_..._format() functions used */
typedef struct _item_label_t {
    char representation[ITEM_LABEL_LENGTH];
} item_label_t;

/** Contains the field information for the proto_item. */
typedef struct field_info {
    const hf_info  *hfinfo;          /**< pointer to registered field information */
    int             start;           /**< current start of data in field_info.ds_tvb */
    int             length;          /**< current data length of item in field_info.ds_tvb */
    int             appendix_start;  /**< start of appendix data */
    int             appendix_length; /**< length of appendix data */
    int             tree_type;       /**< one of ETT_ or -1 */
    uint32_t        flags;           /**< bitfield like FI_GENERATED, ... */
    item_label_t   *rep;             /**< string for GUI tree */
    tvbuff_t       *ds_tvb;          /**< data source tvbuff */
    fvalue_t       *value;
    int             total_layer_num;  /**< Hierarchical layer number, for all protocols in the tree. */
    int             proto_layer_num;  /**< Protocol layer number, so 1st, 2nd, 3rd, ... for protocol X. */
} field_info;

/** One of these exists for the entire protocol tree. Each proto_node
 * in the protocol tree points to the same copy. */
typedef struct {
    GHashTable         *interesting_hfids;
    bool                visible;
    bool                fake_protocols;
    unsigned            count;
    packet_info        *pinfo;
} tree_data_t;

/** Each proto_tree, proto_item is one of these. */
typedef struct _proto_node {
    struct _proto_node *first_child;
    struct _proto_node *last_child;
    struct _proto_node *next;
    struct _proto_node *parent;
    field_info         *finfo;
    tree_data_t        *tree_data;
} proto_node;


/** A protocol tree element. */
typedef proto_node proto_tree;
/** A protocol item element. */
typedef proto_node proto_item;

struct _protocol {
    const char *name;               /* long description */
    const char *short_name;         /* short description */
    const char *filter_name;        /* name of this protocol in filters */
    GPtrArray  *fields;             /* fields for this protocol */
    int         proto_id;           /* field ID for this protocol */
    bool        is_enabled;         /* true if protocol is enabled */
    bool        enabled_by_default; /* true if protocol is enabled by default */
    bool        can_toggle;         /* true if is_enabled can be changed */
    int         parent_proto_id;    /* Used to identify "pino"s (Protocol In Name Only).
                                       For dissectors that need a protocol name so they
                                       can be added to a dissector table, but use the
                                       parent_proto_id for things like enable/disable */
};
typedef struct _protocol protocol_t;

enum dissector_e {
    DISSECTOR_TYPE_SIMPLE,
    DISSECTOR_TYPE_CALLBACK
};
typedef int (*dissector_t)(tvbuff_t *, packet_info *, proto_tree *, void *);

/*
 * A dissector handle.
 */
struct dissector_handle {
    const char *name;           /* dissector name */
    const char *description;    /* dissector description */
    char       *pref_suffix;
    enum dissector_e dissector_type;
    union {
        dissector_t    dissector_type_simple;
//        dissector_cb_t    dissector_type_callback;
    } dissector_func;
    void       *dissector_data;
    protocol_t *protocol;
};


/* Dissection of a single byte array. Holds tvbuff info as
 * well as proto_tree info. 
 */
struct _lua_dissector {
    tvbuff_t    *tvb;
    proto_tree  *tree;
    packet_info  pi;
};
typedef struct _lua_dissector lua_dissector_t;


/*
 * A dissector table.
 *
 * "hash_table" is a hash table, indexed by port number, supplying
 * a "struct dtbl_entry"; it records what dissector is assigned to
 * that uint or string value in that table.
 *
 * "dissector_handles" is a list of all dissectors that *could* be
 * used in that table; not all of them are necessarily in the table,
 * as they may be for protocols that don't have a fixed uint value,
 * e.g. for TCP or UDP port number tables and protocols with no fixed
 * port number.
 *
 * "ui_name" is the name the dissector table has in the user interface.
 *
 * "type" is a field type giving the width of the uint value for that
 * dissector table, if it's a uint dissector table.
 *
 * "param" is the base in which to display the uint value for that
 * dissector table, if it's a uint dissector table, or if it's a string
 * table, true/false to indicate case-insensitive or not.
 *
 * "protocol" is the protocol associated with the dissector table. Used
 * for determining dependencies.
 */
struct dissector_table {
    GHashTable *hash_table;
    GSList     *dissector_handles;
    const char *ui_name;
    ftenum_t    type;
    int         param;
    protocol_t *protocol;
    GHashFunc   hash_func;
    bool        supports_decode_as;
};
